<template>
  <div :class="`${inline ? 'flex' : ''}`">
    <div class="flex-wp">
      <div
        class="avatar-uploader"
        :style="{ width: width + 'px', height: height + 'px' }"
        v-for="(item, index) in fileList"
        :key="index"
        @mouseover="currentIndex = index"
        @mouseleave="currentIndex = -1"
      >
        <div class="hover-dialog" v-if="currentIndex === index && !disabled">
          <el-icon
            class="hover-icon"
            :style="{ marginLeft: preview ? '10px' : 0 }"
            @click="deleteImg(index)"
          >
            <Delete />
          </el-icon>
        </div>
        <el-image
          :style="{
            borderRadius: '4px',
            width: width - 2 + 'px',
            height: height - 2 + 'px'
          }"
          :src="item.url"
          :preview-src-list="[item.url]"
          fit="contain"
        />
      </div>
      <el-upload
        v-if="fileList.length < limit"
        :accept="accept"
        :disabled="disabled"
        :class="['avatar-uploader', { isDisabled: disabled }]"
        :style="{ width: width + 'px', height: height + 'px' }"
        action="#"
        :http-request="uploadAction"
        :show-file-list="false"
        :before-upload="beforeAvatarUpload"
      >
        <div
          :class="['flex-ac-jc', { isDisabled: disabled }]"
          :style="{
            width: width - 2 + 'px',
            height: height - 2 + 'px',
            borderRadius: '4px'
          }"
        >
          <el-icon size="22" color="#aaa"><Upload /></el-icon>
          <div style="color: #aaa; padding-top: 8px">上传图片</div>
        </div>
        <div
          class="flex-ac-jc"
          v-if="showLoading"
          :style="{
            position: 'absolute',
            zIndex: 9,
            background: '#fff',
            top: 0,
            left: 0,
            width: width - 2 + 'px',
            height: height - 2 + 'px',
            borderRadius: '4px'
          }"
        >
          <div :style="{ width: width - 8 + 'px', height: '10px' }">
            <el-progress :percentage="50" indeterminate :show-text="false" />
          </div>
          <div style="color: #555; padding-top: 8px">上传中...</div>
        </div>
      </el-upload>
    </div>
    <div v-if="tips" :class="`${inline ? 'rowTip' : 'colTip'}`" style="line-height: 16px">
      {{ tips }}
    </div>
  </div>
</template>

<script setup>
import { computed, ref } from 'vue'
import { elMessage } from '../../ele-message'
import axios from 'axios'
import { Delete, Upload } from '@element-plus/icons-vue'
const emits = defineEmits(['update:modelValue'])
const showLoading = ref(false)
const currentIndex = ref(-1)
const props = defineProps({
  // 图片列表
  modelValue: {
    type: Array,
    default: () => {
      return []
    }
  },
  // 图片宽度
  width: {
    type: [Number, String],
    default: 100
  },
  // 图片高度
  height: {
    type: [Number, String],
    default: 100
  },
  // 最大上传数
  limit: {
    type: [Number, String],
    default: 5
  },
  // 图片是否可以预览
  preview: {
    type: Boolean,
    default: false
  },
  // 可上传文件类型
  accept: {
    type: String,
    default: '.png,.jpg,.jpeg'
  },
  // 上传尺寸
  size: {
    type: [String, Number],
    default: 1024 * 10
  },
  // 上传尺寸说明
  sizeType: {
    type: String,
    default: 'kb'
  },
  // 上传文件描述文本
  tips: {
    type: String,
    default: ''
  },
  //是否一行显示
  inline: {
    type: Boolean,
    default: true
  },
  // 上传图片宽度
  limitWidth: {
    type: String,
    default: ''
  },
  // 上传图片高度
  limitHeight: {
    type: String,
    default: ''
  }
})

/**
 * 上传图片列表
 */
const fileList = computed({
  get() {
    return props.modelValue
  },
  set(n) {
    emits('update:modelValue', n)
  }
})

/**
 * 获取上传图片的高宽
 * @param { file } file 附件
 */
const getFile = async (file) => {
  const reader = new FileReader()
  reader.readAsDataURL(file)
  return new Promise((resolve) => {
    reader.onload = (e) => {
      resolve(e.target.result)
    }
  })
}
const getWidth = async (file) => {
  const result = await getFile(file)
  const img = new Image()
  img.src = result
  return new Promise((resolve) => {
    img.onload = () => {
      const width = img.width
      const height = img.height
      resolve({ width, height })
    }
  })
}

/**
 * 对上传的图片进行校验
 * 判断图片类型
 * 判断图片宽高
 * 判断图片尺寸
 * @param { file } rawFile
 */
const beforeAvatarUpload = async (rawFile) => {
  const { width, height } = await getWidth(rawFile)
  let { type } = rawFile
  if (props.accept && props.accept.indexOf(type.split('/')[1]) === -1) {
    elMessage({
      type: 'error',
      message: '请上传规定类型的图片'
    })
    return false
  } else if (props.limitWidth && (props.limitWidth != width || props.limitHeight != height)) {
    elMessage({
      type: 'error',
      message: `请上传宽高为${props.limitWidth}px*${props.limitHeight}px的图片`
    })
    return false
  }
  return true
}

/**
 * 上传处理图片
 * @param { file } file 图片文件
 */
const uploadAction = async ({ file }) => {
  showLoading.value = true
  try {
    const url = `https://canpointtest.com/frontEnd/ossApi/upload-oss-npm?key=891017`
    const formData = new FormData()
    formData.append('file', file)
    const { data } = await axios.post(url, formData, {
      Headers: {
        'content-type': 'multipart/form-data'
      }
    })
    fileList.value.push({
      url: data.data
    })
    elMessage({
      type: 'success',
      message: '上传成功'
    })
  } catch (err) {
    console.log(err)
    elMessage({
      type: 'success',
      message: '上传失败'
    })
  }
  showLoading.value = false
}

// 删除图片
const deleteImg = (index) => {
  fileList.value.splice(index, 1)
}
</script>

<style scoped lang="scss">
.flex-wp {
  display: flex;
  flex-wrap: wrap;
}
.flex {
  display: flex;
}
.flex-ac-jc {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.colTip {
  color: #999;
  font-size: 12px;
  padding-top: 10px;
}

.rowTip {
  color: #999;
  font-size: 14px;
  height: 100px;
  display: flex;
  align-items: flex-end;
}

.avatar-uploader {
  position: relative;
  border: 1px #ddd solid;
  border-radius: 4px;
  margin-right: 12px;
  display: flex;
  justify-content: center;
  align-items: center;

  img {
    border-radius: 6px;
    display: block;
  }
}

.avatar-uploader-icon {
  border-radius: 6px;
  font-size: 28px;
  color: #999;
}

.hover-dialog {
  position: absolute;
  width: 100%;
  height: 22px;
  bottom: 0px;
  z-index: 999;
  border-radius: 0px 0px 4px 4px;
  background: rgba(0, 0, 0, 0.6);
  line-height: 22px;
  text-align: center;

  .hover-icon {
    font-size: 16px;
    padding-top: 5px;
    color: #fff;
    cursor: pointer;
  }
}

.file-list {
  position: relative;
  padding: 0 20px;
  height: 80px;
  border: 1px solid #eee;
  border-radius: 6px;
  margin-top: 10px;
}
</style>
